package com.qiantu.confignetwork.hiflying.aplink.v1;

import java.util.Arrays;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESCrypt {
//	private static final String aesKey= "1234567890ABCDEF";
	private static String aesKey= "`aPliNkseRViCe$'";
	
	public static void setAESKey(String key) {
		aesKey= key;
	}
	
	public static byte[] HFEncrypt(byte[] bSrc){
		if (bSrc==null){
			return null;
		}
		try {
			byte[] padSrc= padding(bSrc, 16);
			byte[] ret= EncryptCBC(padSrc, aesKey);
			return ret;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	private static byte[] padding(byte[] bSrc, int blockNum){
		int len= bSrc.length;
		if (len % blockNum==0){
			return bSrc;
		}else{
			len= (len/blockNum+1)*blockNum;
			byte[] pad= new byte[len];
			Arrays.fill(pad, (byte)0);
			System.arraycopy(bSrc, 0, pad, 0, bSrc.length);
			return pad;
		}
	}
	
	public static byte[] HFDecrypt(byte[] encrypted){
		if (encrypted==null){
			return null;
		}
		try {
			byte[] ret= DecryptCBC(encrypted, aesKey);
			return ret;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public static byte[] unPadding(byte[] src){
		if (src==null){
			return null;
		}
		int len= src.length-1;
		while (len>=0){
			if (src[len]==0){
				len--;
			}else{
				break;
			}
		}
		byte[] ret= new byte[len+1];
		System.arraycopy(src, 0, ret, 0, len+1);
		return ret;
	}
	
	private static byte[] EncryptCBC(byte[] bSrc, String sKey){
		if (sKey == null) {
            System.out.print("Key cann't be null");
            return null;
        }
        if (sKey.length() != 16) {
            System.out.print("Key must be 16-byte");
            return null;
        }
        
        try {
			IvParameterSpec iv = new IvParameterSpec(sKey.getBytes());
			SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(), "AES");
			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
			
			byte[] encrypted = cipher.doFinal(bSrc);
			return encrypted;
        } catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
	}
	
	private static byte[] DecryptCBC(byte[] encrypted, String sKey){
		if (sKey == null) {
            System.out.print("Key cann't be null");
            return null;
        }
        if (sKey.length() != 16) {
            System.out.print("Key must be 16-byte");
            return null;
        }
        if (encrypted.length % 16 != 0) {
            System.out.print("encrypted string should be multiple of 16-byte");
            return null;
        }
        
		try {
			IvParameterSpec iv = new IvParameterSpec(sKey.getBytes());
			SecretKeySpec skeySpec = new SecretKeySpec(sKey.getBytes(), "AES");
			Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
			cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
			try {
	            byte[] original = cipher.doFinal(encrypted);
	            return original;
	        } catch (Exception e) {
	            System.out.println(e.toString());
	            return null;
	        }
		} catch (Exception ex) {
            System.out.println(ex.toString());
            return null;
        }
	}
    
    public static String byteToHexString(byte[] bytes){
    	if (bytes==null){
    		return "byteToHexString::input is null";
    	}
    	String str= "";
    	for (int i=0; i<bytes.length; i++){
    		str+= String.format("%02X", bytes[i]);
    	}
    	return str;
    }
    
    public static byte[] hexStringToByte(String str){
    	int len= str.length();
    	int byteLen= len/2;
    	byte first= 0;
    	int pos= 0, bytePos= 0;
    	if (byteLen*2!=len){
    		byteLen+=1;
    		first= _hexToByte((byte)'0', (byte)str.charAt(pos));
    		pos++;
    	}else{
    		first= _hexToByte((byte)str.charAt(pos), (byte)str.charAt(pos+1));
    		pos+=2;
    	}
    	if (first==-1)
    		return null;
    	byte[] b= new byte[byteLen];
    	b[bytePos]= first;
		bytePos++;
    	while (bytePos<byteLen){
    		first= _hexToByte((byte)str.charAt(pos), (byte)str.charAt(pos+1));
    		if (first==-1)
        		return null;
    		b[bytePos]= first;
    		pos+=2;
    		bytePos++;
    	}
    	return b;
    }
    
    private static byte _hexToByte(byte b1, byte b2){
    	byte ret1= _h2b(b1);
    	if (ret1==-1)
    		return -1;
    	byte ret2= _h2b(b2);
    	if (ret1== -1)
    		return -1;
    	return (byte) ((ret1<<4)+ret2);
    }
    
    private static byte _h2b(byte b){
    	if (b>='0' && b<='9'){
    		return (byte) (b-'0');
    	}else if (b>='a' && b<='f'){
    		return (byte) (b-'a'+10);
    	}else if (b>='A' && b<='F'){
    		return (byte) (b-'A'+10);
    	}
    	return -1;
    }
}
